<?php
/**
 * Created by PhpStorm.
 * User: jjj
 * Date: 2017/11/20
 * Time: 14:07
 */

namespace app\callback\controller;


use app\admin\model\live\LiveChannel;
use app\api\model\curriculum\Curriculum;
use app\api\model\live\Live;
use app\common\model\app\ConstLinkType;
use app\common\model\curriculum\CurriculumVideo;
use app\common\model\UserNoticeMessage;
use app\common\model\VideoStorage;
use library\JPushZDY;
use library\v163Class;
use think\Db;
use think\db\Query;
use think\Exception;
use think\Log;
use think\Request;

/**
 * 网易视频直播回调
 *
 * Class Netease
 * @package app\callback\controller
 *
 * @property v163Class v163
 * @property array params
 */
class Netease
{
    private $v163;
    private $params;

    /**
     * 视频点播：检查网易回调签名，解析参数
     *
     * Netease constructor.
     */
    public function vodCheckSign()
    {
        $request = Request::instance();
        $sign = $request->header('sign');
        if (!$sign) $this->return_direct();

        $body = file_get_contents('php://input');
        $this->v163 = v163Class::getInstance();
        if ($this->v163->verifyVodCallbackSign($sign, $body) == false)
            $this->return_direct();

        $this->params = json_decode($body,true);
    }

    public function liveCheckSign()
    {
        $request = Request::instance();
        $sign = $request->header('sign');
        if (!$sign) $this->return_direct();

        $body = file_get_contents('php://input');
        $this->v163 = v163Class::getInstance();
        $this->params = json_decode($body,true);
        if ($this->v163->verifyLiveCallbackSign($sign, $this->params) == false) {
            $this->return_direct();
        }
    }

    private function Param($key = null) {
        if (is_null($key)) return $this->params;
        else return $this->params[$key] ?? null;
    }
    private function return_direct($data = null, $status = 200) {
        http_response_code($status);
        echo $data;
        die;
    }

    /**
     * @deprecated
     * 直播频道状态回调
     */
    public function channel_status() {
        $this->liveCheckSign();

        Db::transaction(function () {

            $cid = $this->Param('cid');
            $status = intval($this->Param('status'));
            $time = intval($this->Param('time') * 0.001);
            $liveStat = LiveChannel::STATUS_MAP_NET_EASE[$status];

            $channel = LiveChannel::getByCID($cid);
            $channel->status = $liveStat;
            $channel->save();
        });

        $this->return_direct();
    }

    /**
     * 直播录制
     */
    public function live_record() {

        $this->liveCheckSign();

        try{
            Db::startTrans();

            $cid = $this->Param('cid');
            $channel = LiveChannel::get(['cid' => $cid]);
            if (empty($channel)) {
                Log::error(new Exception('频道不存在:'.$cid));
                $this->return_direct();
            }

            $beginTime = $this->Param('beginTime');
            $endTime = $this->Param('endTime');
            $recordCall = ($beginTime && $endTime);
            if ($recordCall) {
                // 录制回调通知
                $midTime = intval(($beginTime/1000 + $endTime/1000)/2);
                $middleTime = date('Y-m-d H:i:s',$midTime);
                $live = Live::get(function (Query $query) use ($channel,$middleTime) {
                    $query->where('live_channel_id','=', $channel->id);
                    $query->where('start_time','<=', $middleTime);
                    $query->where('end_time','>=', $middleTime);
                });
                if (empty($live)) {
                    Log::error(new Exception("直播节目不存在:".$middleTime));
                    $this->return_direct();
                }

                $liveStartTime = strtotime($live->start_time);
                $liveEndTime = strtotime($live->end_time);
                $liveEnded = (time() >= $liveEndTime && 2 == $live->status);
                //回看上传失败bug--modify cc 2018-10-23
                $origUrl = $this->Param('origUrl');

                if (false == $liveEnded && !$origUrl) return; // 直播未结束

                $vodList = $this->v163->channel_vodVideoList($cid, ($liveStartTime-60)*1000,($liveEndTime+60)*1000);
                $list = [];
                foreach ($vodList as $item) {
                    $midTime = intval(($item['beginTime']/1000 + $item['endTime']/1000)/2);
                    if ($liveStartTime < $midTime && $midTime < $liveEndTime) $list[] = $item;
                }
                if (count($list) > 1) {
                    // 如果多个视频，调用合并
                    $vidList = array_column($list,'vid');
                    $this->v163->channel_vodMerge('live-'.$live->id, $vidList);
                    $this->return_direct();
                } elseif (count($list) < 1) {
                    $this->return_direct();
                }
                // 只有一个视频，继续
            } else {
                // 合并录制视频回调通知
                $video_name = $this->Param('video_name');
                $liveId = explode('-',$video_name)[1] ?? 0;
                $live = Live::get($liveId);
                if (empty($live)) {
                    Log::error(new Exception("直播节目不存在:".$video_name));
                    $this->return_direct();
                }
            }

            // 查询视频详情
            $vid = $this->Param('vid');
            $ret = $this->v163->vod_get($vid);

            $vs = new VideoStorage();
            $vs->netease_vid = $vid;
            $vs->netease_orig_addr = $ret['origUrl'];
            $vs->save();

            $live->vid = $vs->id;
            $live->video_url = $vs->netease_orig_addr;
            $live->status = 3;
            $live->save();

            Db::commit();
        }catch (\Exception $ex){
            Db::rollback();
            Log::error('直播录制回调出错:'.$ex->getCode().' => '.$ex->getMessage());
            Log::error('参数:'.print_r($this->params,true));
        }

    }

    /**
     * 上传视频完成
     */
    public function upload_finish() {

        $this->vodCheckSign();

        if ('upload' == $this->Param('type')) {
            $vid = $this->Param('vid');
            $userDefined = explode('=', $this->Param('user_defined'));
            $video_id = intval($userDefined[1] ?? 0);
            $video = CurriculumVideo::get($video_id);
            $vs = VideoStorage::get($video->vid);
            if ($vs->netease_vid) { // 删除已存在
                $this->v163->vod_del($vs->netease_vid);
            }
            $origAddr = $this->Param('origAddr');
            $vs->netease_vid = $vid;
            $vs->name = $this->Param('name');
            $vs->netease_orig_addr = $origAddr;
            $vs->netease_status = VideoStorage::NETEASE_STATUS_UPLOAD_FINISH;
            $vs->isUpdate(true);
            $vs->save();

            // 兼容`v1.0`，保存原视频地址到`curriculum_video`
            $video->video_url = $origAddr;
            $video->save();
        }

        $this->return_direct();
    }

    /**
     * 转码和加密完成
     */
    public function transcode_finish() {

        $this->vodCheckSign();

        $error = $this->Param('error');
        if ($error) {
            Log::error($error);
            $this->return_direct();
        }

        $vid = $this->Param('vid');
        $vs = VideoStorage::getByVID($vid);
        if ('transcode' == $this->Param('type')) {
            $msg = $this->Param('msg');
            if ('failed' == $msg) {
                Log::error('转码失败：'.$vs.', '.$msg);
                $this->return_direct();
            }

            // 删除之前的加密视频
            $list = VideoStorage::getEncrypt($vs->id);
            foreach ($list as $ne) {
                $this->v163->vod_encrypt_delete($ne['encrypt_id']);
            }
            VideoStorage::deleteEncrypt($vs->id);

            // 加密三种清晰度的flv视频
            try{
                foreach (v163Class::$SupportStyles as $style) {
                    $re = $this->v163->vod_encrypt_create($vs->netease_vid, $style);
                    $vs->createEncrypt($re['encryptId'], $style);
                }
            }catch (\Exception $e){
                Log::error('加密：'.$e->getMessage());
            }

            $vs->netease_status = VideoStorage::NETEASE_STATUS_TRANSCODE_FINISH;
            $vs->save();

        } elseif ('encrypt' == $this->Param('type')) {
            $encryptId = $this->Param('encryptId');
            $playUrl = $this->Param('playUrl');
            VideoStorage::storeEncrypt($encryptId, $playUrl);

            $vs->netease_status = VideoStorage::NETEASE_STATUS_ENCRYPT_FINISH;
            $vs->save();

            $video = CurriculumVideo::get(function ($query) use ($vs) {
                $query->alias('cv');
                $query->join('curriculum c', 'cv.video_curriculum=c.curriculum_id', 'left');
                $query->where('c.curriculum_type', '<>', 3);
                $query->where('cv.video_id', $vs->id);
            });
            if ($video) {
                // 字段修改视频状态
                $video->setHide(false);

                $curri = Curriculum::get(function (Query $query) use ($video){
                    $query->where('curriculum_id',$video->video_curriculum);
                    $query->field('curriculum_id, curriculum_name');
                });

                // todo 先酱紫，稍后优化
                $users = Curriculum::getBoughtUsersID($video->video_curriculum);
                $content = sprintf('掌乾财经：您所购买的课程《%s》有更新了，赶快去看看吧。详情点击',$curri->curriculum_name);
                $extras = UserNoticeMessage::makeExtras(ConstLinkType::LINK_TYPE_CURRICULUM, $curri->curriculum_id);
                JPushZDY::pushUsers($users,$content, $extras);
            }
        }

        $this->return_direct();
    }

    public function _empty() {
        echo 1;
    }
}
